#include <bits/stdc++.h>
using namespace std;
const int N = 1000 + 10, Q = 8;
int n, x[N], y[N], cost[N];
vector<int> subn[Q];
int pa[N];
int findset(int x) { return pa[x] != x ? pa[x] = findset(pa[x]) : x; }

struct Edge {
  int u, v, d;
  Edge(int u, int v, int d) : u(u), v(v), d(d) {}
  bool operator<(const Edge& rhs) const { return d < rhs.d; }
};

/**
 * @brief 求MST
 *
 * initialize ``pa`` and sort ``e`` before calling this method.
 * ``cnt`` is the current number of components
 *
 * @param cnt 当前连通分量的个数
 * @param e 可用的边集
 * @param used 返回已使用的边集
 * @return 新加入MST的边的权重之和
 */
int MST(int cnt, const vector<Edge>& e, vector<Edge>& used) {
  if (cnt == 1) return 0;
  int m = e.size();
  int ans = 0;
  used.clear();
  for (int i = 0; i < m; ++i) {
    int u = findset(e[i].u), v = findset(e[i].v);
    int d = e[i].d;
    if (u != v) {
      pa[u] = v;
      ans += d;
      used.push_back(e[i]);
      if (--cnt == 1) break;
    }
  }
  return ans;
}

int main() {
  int T, q;
  scanf("%d", &T);
  while (T--) {
    scanf("%d%d", &n, &q);
    for (int i = 0; i < q; ++i) {
      int cnt;
      scanf("%d%d", &cnt, &cost[i]);
      subn[i].clear();  // 清掉上一次的，别忘了
      while (cnt--) {
        int u;
        scanf("%d", &u);
        subn[i].push_back(u - 1);
      }
    }
    for (int i = 0; i < n; ++i) scanf("%d%d", &x[i], &y[i]);

    vector<Edge> e,  // 边集
        need;  // 如果某条边不在MST中，这条边也不会出现在买了子网后的生成树中。
    for (int i = 0; i < n; ++i)
      for (int j = i + 1; j < n; ++j) {
        int c = (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]);
        e.push_back(Edge(i, j, c));
      }

    for (int i = 0; i < n; ++i) pa[i] = i;
    sort(e.begin(), e.end());

    int ans = MST(n, e, need);  // 1. 一个都不买
    // 2. 至少买一个
    for (int mask = 1; mask < (1 << q); ++mask) {
      // 买下子网，将子网内部连到一起
      for (int i = 0; i < n; ++i) pa[i] = i;
      int cnt = n,  // 最开始，有n个连通分量
          c = 0;    // 本次花费
      for (int i = 0; i < q; ++i)
        if (mask & (1 << i)) {
          c += cost[i];  // 买子网，加到同一个连通分量中
          for (int j = 1; j < subn[i].size(); ++j) {
            int u = findset(subn[i][j]), v = findset(subn[i][0]);
            if (u != v) {
              pa[u] = v;
              cnt--;
            }
          }
        }
      vector<Edge> dummy;

      // 子网消耗 + 继续连通
      ans = min(ans, c + MST(cnt, need, dummy));
    }
    printf("%d\n", ans);
    if (T) printf("\n");
  }
  return 0;
}
